const md5 = require('md5')
const xml2js = require('xml2js')
const Parser = new xml2js.Parser()
const uuid = require('uuid/v4')
const randomChar = uuid().toString().replace(/-/g, '') //随机生成的字符串

const request = require('request')
const prepay_url = 'https://api.mch.weixin.qq.com/pay/unifiedorder'

module.exports = async function prepay(openid, orderID, requestIP, total_fee) {
  const obj = {
    appid: 'wx3ba6230358b8558a',
    body: 'Qolay便利服务商品',
    mch_id: 1517033051,
    nonce_str: randomChar,
    openid: openid,
    notify_url: 'http://wx.2xur7.cn/weapp/payReturn',
    out_trade_no: orderID,
    spbill_create_ip: requestIP,
    total_fee: total_fee,
    trade_type: 'JSAPI'
  }
//   console.log(obj);
  let arr = Object.keys(obj).sort().map(item => {
    return `${item}=${obj[item]}`;
  });
  // 这里拼接签名字符串的时候一定要注意: 商户的key是要单独拿出来拼在最后面的
  let str = arr.join('&') + '&key=fa88a8e559d34bf199cd1c5b2032a2c5';

  obj.sign = getSign(str);
  let res;
  try {
    // 调用微信统一下单接口拿到 prepay_id
    res = await wechatPay(obj);
    let {
      prepay_id
    } = res;
    if (prepay_id) {
      res = getClientPayConfig(prepay_id)
    }
    // console.log(res);
  } catch (e) {
    res = e;
    console.log(e);
  }
  return res;
}


/**
 * 统一下单 prepay_url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
 * @param {Object} obj 调用统一下单的必须参数
 */
const wechatPay = (obj) => {
  let xml = json2xml(obj);
//   console.log(xml)
  return new Promise((resolve, reject) => {
    // 这里用了reques库,不熟悉的同学可以看看相关文档 https://github.com/request/request
    // 总之就是向微信的统一下单接口提交一个xml
    request({
      method: 'POST',
      url: prepay_url,
      body: xml
    }, (err, res, body) => {
      if (err) {
        reject(err);
      } else {
        //如果成功即可得到微信返回参数
        // console.log(body);
        let obj = parseXml(body).xml;
        resolve(obj);
      }
    });
  });
}


/**
 * 对指定字符串进行md5加密
 * @param {String} str 
 */
const getSign = (str) => {
  return md5(str).toUpperCase();
  s
}

/**
 * 转化xml用了xml2js库  
    https://github.com/Leonidas-from-XIV/node-xml2js
 * @param {Object} obj 
 */
const json2xml = (obj) => {
  let builder = new xml2js.Builder({
    headless: true,
    allowSurrogateChars: true,
    rootName: 'xml',
    cdata: true
  });
  var xml = builder.buildObject(obj);
  return xml;
}

const parseXml = (xml) => {
  let {
    parseString
  } = xml2js;
  let res;
  parseString(xml, {
    trim: true,
    explicitArray: false
  }, function (err, result) {
    res = result;
  });
  return res;
}

/**
 * 生成指定长度的随机数
 * @param {*int} len 
 */
/* 
const get_nonce_str = (len) => {
  let str = '';
  while (str.length < len) {
    str += Math.random().toString(36).slice(2);
  }
  return str.slice(-len);
} */
const getClientPayConfig = (prepay_id) => {
  let obj = {
    appId: 'wx3ba6230358b8558a',
    timeStamp: String(Math.floor(Date.now() / 1000)),
    nonceStr: randomChar,
    package: 'prepay_id=' + prepay_id,
    signType: 'MD5'
  }
  let arr = Object.keys(obj).sort().map(item => {
    return `${item}=${obj[item]}`;
  });
  let str = arr.join('&') + '&key=fa88a8e559d34bf199cd1c5b2032a2c5';
  obj.paySign = getSign(str);
  return obj;
}
